package heima_bixiangdong.test.jdk5;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @DESCRIPTION:    JDK1.5里面自带的多生产多消费的例子
 * @USER: shg
 * @DATE: 2022/11/26 18:08
 */
public class JDK5_Lock_Condition_Demo {
    public static void main(String[] args) {
        // 资源对象
        BoundedBuffer boundedBuffer = new BoundedBuffer();

        // 生产任务和消费任务
        Producer_5 producer = new Producer_5(boundedBuffer);
        Consumer_5 consumer = new Consumer_5(boundedBuffer);

        // 开启两个生产线程和消费线程，分别执行生产任务和消费任务
        Thread t1 = new Thread(producer);
        Thread t2 = new Thread(producer);
        Thread t3 = new Thread(consumer);
        Thread t4 = new Thread(consumer);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

// 生产任务
class Producer_5 implements Runnable{
    private BoundedBuffer boundedBuffer;


    public Producer_5(BoundedBuffer boundedBuffer) {
        this.boundedBuffer = boundedBuffer;
    }


    @Override
    public void run() {
        while (true){
            try {
                boundedBuffer.put(new Object());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 消费任务
class Consumer_5 implements Runnable{
    private BoundedBuffer boundedBuffer;


    public Consumer_5(BoundedBuffer boundedBuffer) {
        this.boundedBuffer = boundedBuffer;
    }

    @Override
    public void run() {
        while (true){
            try {
                boundedBuffer.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

// 资源对象
class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition();
    final Condition notEmpty = lock.newCondition();

    final Object[] items = new Object[20];
    int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();
            items[putptr] = x;
            if (++putptr == items.length) putptr = 0;
            ++count;
            System.out.println(Thread.currentThread().getName()+"...生产者..."+count+"--->");
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            Object x = items[takeptr];
            if (++takeptr == items.length) takeptr = 0;
            --count;
            System.out.println(Thread.currentThread().getName()+"...消费者..."+count+"--->");
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}
